package when3meet.controller;

import java.awt.Color;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.JFileChooser;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.util.Rotation;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import client.ServerAccess;

import when3meet.model.ClientInfo;
import when3meet.view.AdminFrame;
import when3meet.view.Application;
import xml.Message;

public class ReportController implements ActionListener {

	static File file;
	// statistic for all events
	int completedTotal = 0;
	int unCompletedTotal = 0;
	int numOfAsyn = 0;
	int numOfRR = 0;

	// statistic for asynchronous and round-robin
	int numOfUncompletedAsyn = 0;
	int numOfUncompletedRR = 0;

	// average number of choices and rounds for asynchronous, round-robin
	// respectively
	int numOfAsynChoices = 0;
	int numOfAsynRounds = 0;
	int numOfRRChoices = 0;
	int numOfRRRounds = 0;

	/**
	 * This controller send report request to server, and handle report response
	 * from server, generate a report in local HTML file
	 * 
	 * @param response
	 */
	public void process(Message response) {

		String type = "";
		type = getType();

		// get statistic from server's response

		Node update = response.contents.getFirstChild();
		NodeList children = update.getChildNodes();

		for (int i = 0; i < children.getLength(); i++) {
			Node n = children.item(i);
			NamedNodeMap tempMap = n.getAttributes();
			if (n.getNodeName().equalsIgnoreCase("entry")) {
				String behavior = tempMap.getNamedItem("behavior").getNodeValue();
				if (behavior.equals("asynchronous")) {
					// expand number of asynchronous event by 1 first
					numOfAsyn++;

					// judge whether this event is completed or not, then add
					// the corresponding number
					String completed = tempMap.getNamedItem("completed").getNodeValue();
					if (completed.equals("false")) {
						// add number of uncompleted event by 1
						numOfUncompletedAsyn++;
					}

					// store number of choices and rounds;
					int numChoices = Integer.parseInt(tempMap.getNamedItem("numChoices").getNodeValue());
					int numRounds = Integer.parseInt(tempMap.getNamedItem("numRounds").getNodeValue());

					numOfAsynChoices += numChoices;
					numOfAsynRounds += numRounds;

				} else if (behavior.equals("roundRobin")) {
					// expand number of round-robin event by 1
					numOfRR++;

					String completed = tempMap.getNamedItem("completed").getNodeValue();
					if (completed.equals("false")) {
						// add number of uncompleted event by 1
						numOfUncompletedRR++;
					}

					// store number of choices and rounds

					int numChoices = Integer.parseInt(tempMap.getNamedItem("numChoices").getNodeValue());
					int numRounds = Integer.parseInt(tempMap.getNamedItem("numRounds").getNodeValue());

					numOfRRChoices += numChoices;
					numOfRRRounds += numRounds;
				}
			}

			completedTotal = children.getLength();
			unCompletedTotal = numOfUncompletedAsyn + numOfUncompletedRR;

		}

		getChart();

		BufferedWriter bw;
		try {

			BufferedReader br = new BufferedReader(new FileReader("style.css"));

			File f = new File(file + "/" + "report.html");
			bw = new BufferedWriter(new FileWriter(f));
			bw.write("<!DOCTYPE html>");
			String line;
			while ((line = br.readLine()) != null) {
				bw.write(line);
				bw.newLine();
			}
			br.close();

			bw.write("<html>");
			bw.write("<body>");
			bw.write("<h2 text-algin=\"center\">Decision Line System Report for " + type + " Event" + "</h1>");
			bw.write("<div class=\"chart-container\">");
			bw.write("<h5>Completed/Uncompleted</h5>");
			bw.write("<img class=\"image\" src=\"chart1.png\" height=\"240\" width=\"340\">");
			bw.write("</div>");

			bw.write("<div class=\"chart-container\">");
			bw.write("<h5>Asynchronous/Round-Robin</h5>");
			bw.write("<img class=\"image\" src=\"chart2.png\" height=\"240\" width=\"340\">");
			bw.write("</div>");

			bw.write("<div class=\"chart-container\">");
			bw.write("<h5>Stat for Asynchronous(Average)</h5>");
			bw.write("<img class=\"image\" src=\"chart3.png\" height=\"240\" width=\"340\">");
			bw.write("</div>");

			bw.write("<div class=\"chart-container\">");
			bw.write("<h5>Stat for Round-Robin(Average)</h5>");
			bw.write("<img class=\"image\" src=\"chart4.png\" height=\"240\" width=\"340\">");
			bw.write("</div>");

			bw.write("</body>");
			bw.write("</html>");
			bw.close();
			Desktop.getDesktop().browse(f.toURI());
			AdminFrame.getInstance().getDoneLabel().setVisible(true);
		} catch (Exception ec) {
			ec.printStackTrace();
		}
	}

	/**
	 * draw the chart
	 */
	private void getChart() {

		DefaultPieDataset data = new DefaultPieDataset();
		data.setValue("Completed", completedTotal);
		data.setValue("Uncompleted", unCompletedTotal);

		// create the chart...
		JFreeChart chart = ChartFactory.createPieChart3D(null, data, false, false, false);

		PiePlot3D plot = (PiePlot3D) chart.getPlot();
		plot.setStartAngle(0);
		plot.setDirection(Rotation.ANTICLOCKWISE);
		plot.setForegroundAlpha(0.60f);
		plot.setBackgroundAlpha(0);
		plot.setOutlinePaint(null);
		plot.setSectionPaint(1, new Color(215, 117, 95));
		plot.setSectionPaint(0, new Color(95, 215, 123));

		try {
			ChartUtilities.saveChartAsPNG(new File(file + "/" + "chart1.png"), chart, 340, 240, null, true, 0);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// chart 2
		data = new DefaultPieDataset();
		data.setValue("Asynchronous", numOfAsyn);
		data.setValue("Round-Robin", numOfRR);

		// create the chart...
		chart = ChartFactory.createPieChart3D(null, data, false, false, false);

		plot = (PiePlot3D) chart.getPlot();
		plot.setStartAngle(0);
		plot.setDirection(Rotation.ANTICLOCKWISE);
		plot.setForegroundAlpha(0.60f);
		plot.setBackgroundAlpha(0);
		plot.setOutlinePaint(null);
		plot.setSectionPaint(0, new Color(154, 126, 206));
		plot.setSectionPaint(1, new Color(126, 187, 206));

		try {
			ChartUtilities.saveChartAsPNG(new File(file + "/" + "chart2.png"), chart, 340, 240, null, true, 0);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// chart 3
		DefaultCategoryDataset data1 = new DefaultCategoryDataset();
		data1.setValue(numOfAsynChoices / numOfAsyn, "", "Choices");
		data1.setValue(numOfAsynRounds / numOfAsyn, "", "Rounds");
		data1.setValue(numOfAsyn, "", "Created");
		data1.setValue(numOfAsyn - numOfUncompletedAsyn, "", "Completed");

		// create the chart...
		chart = ChartFactory.createBarChart3D("", "", "", data1, PlotOrientation.VERTICAL, false, true, false);
		CategoryPlot p = chart.getCategoryPlot();
		p.setBackgroundAlpha(0);
		p.setBackgroundPaint(null);
		p.setRangeGridlinePaint(Color.DARK_GRAY);
		BarRenderer barRenderer = (BarRenderer) p.getRenderer();
		barRenderer.setSeriesPaint(0, new Color(154, 126, 206));

		try {
			ChartUtilities.saveChartAsPNG(new File(file + "/" + "chart3.png"), chart, 340, 240, null, true, 0);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// chart 4
		DefaultCategoryDataset data2 = new DefaultCategoryDataset();
		data2.setValue(numOfRRChoices / numOfRR, "", "Choices");
		data2.setValue(numOfRRRounds / numOfRR, "", "Rounds");
		data2.setValue(numOfRR, "", "Created");
		data2.setValue(numOfRR - numOfUncompletedRR, "", "Completed");

		// create the chart...
		chart = ChartFactory.createBarChart3D("", "", "", data2, PlotOrientation.VERTICAL, false, true, false);
		p = chart.getCategoryPlot();
		p.setBackgroundAlpha(0);
		p.setBackgroundPaint(null);
		p.setRangeGridlinePaint(Color.DARK_GRAY);
		barRenderer = (BarRenderer) p.getRenderer();
		barRenderer.setSeriesPaint(0, new Color(126, 187, 206));

		try {
			ChartUtilities.saveChartAsPNG(new File(file + "/" + "chart4.png"), chart, 340, 240, null, true, 0);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public void actionPerformed(ActionEvent e) {
		JFileChooser fc = new JFileChooser();

		int returnVal = fc.showSaveDialog(fc);

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			file = fc.getSelectedFile();
			file.mkdir();
			sendRequest();
		}
	}

	private void sendRequest() {

		String xmlString = Message.requestHeader() + "<reportRequest " + "key = '" + ClientInfo.getInstance().getKey()
				+ "' " + "type = '" + getType() + "'/>" + "</request>";

		Message m = new Message(xmlString);

		ServerAccess access;
		access = Application.getInstance().getServerAccess();
		access.sendRequest(m);

	}

	private String getType() {
		if (AdminFrame.getInstance().getRdbtnClosedEvent().isSelected())
			return "closed";
		else
			return "open";
	}

}
